using System;
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Linq;

public class GridManager : MonoBehaviour
{
    public static GridManager instance;

    public List<GridNode> grids;
    public List<Transform> gridTransforms;

    private void Awake()
    {
        instance = this;
    }

    void Start()
    {


        /*grids = new List<GridNode>();

        grids.Add(new GridNode(1, 1));

        grids.Add(new GridNode(2, 1));
        grids.Add(new GridNode(2, 2));

        grids.Add(new GridNode(3, 1));
        grids.Add(new GridNode(3, 2));
        grids.Add(new GridNode(3, 3));
        grids.Add(new GridNode(3, 4));

        grids.Add(new GridNode(4, 1));
        grids.Add(new GridNode(4, 2));
        grids.Add(new GridNode(4, 3));
        grids.Add(new GridNode(4, 4));

        grids.Add(new GridNode(5, 1));
        grids.Add(new GridNode(5, 2));

        grids.Add(new GridNode(6, 1));*/
    }

    public static int GetGridNum(int layer, int number)
    {
        switch (layer)
        {
            case 1:
                if (number != 1)
                {
                    Debug.Log("Get GridNode Number Error");
                    break;
                }
                return 0;
            case 2:
                if (number > 2 || number < 1)
                {
                    Debug.Log("Get GridNode Number Error");
                    break;
                }
                return 0 + number;
            case 3:
                if (number > 4 || number < 1)
                {
                    Debug.Log("Get GridNode Number Error");
                    break;
                }
                return 2 + number;
            case 4:
                if (number > 4 || number < 1)
                {
                    Debug.Log("Get GridNode Number Error");
                    break;
                }
                return 6 + number;
            case 5:
                if (number > 2 || number < 1)
                {
                    Debug.Log("Get GridNode Number Error");
                    break;
                }
                return 10 + number;
            case 6:
                if (number != 1)
                {
                    Debug.Log("Get GridNode Number Error");
                    break;
                }
                return 12 + number;
            default:
                Debug.Log("Get GridNode Layer Error");
                break;
        }
        return -1;
    }

    public GridNode GetGridNode(int layer, int number)
    {
        int num = GetGridNum(layer, number);
        if (num == -1)
        {
            return null;
        }
        return grids[num];
    }

    public List<GridNode> GetNodesByRange(Func<int, int, bool, GridNode, bool> Selector, bool campIsSelf, GridNode gridNode)
    {
        List<GridNode> result = new List<GridNode>();


        foreach (GridNode node in grids)
        {
            if (Selector(node.layer, node.number, campIsSelf, gridNode))
            {
                result.Add(node);
            }
        }

        return result;
    }

    public static Dictionary<(int layer, int number), List<(int layer, int number)>> SubNodeDic
    = new Dictionary<(int layer, int number), List<(int layer, int number)>>
    {
        [(1, 1)] = new List<(int layer, int number)>
        {
            (2,1),(2,2),(3,1),(3,2),(3,3),(3,4)
        },
        [(2, 1)] = new List<(int layer, int number)>
        {
            (3,1),(3,2)
        },
        [(2, 2)] = new List<(int layer, int number)>
        {
            (3,3),(3,4)
        },
        [(6, 1)] = new List<(int layer, int number)>
        {
            (5,1),(5,2),(4,1),(4,2),(4,3),(4,4)
        },
        [(5, 1)] = new List<(int layer, int number)>
        {
            (4,1),(4,2)
        },
        [(5, 2)] = new List<(int layer, int number)>
        {
            (4,3),(4,4)
        }
    };

    public void Clear()
    {
        foreach (var node in grids)
        {
            if (node.Pawn != null)
            {
                if (!node.Pawn.campIsSelf)
                {
                    Debug.Log("yes");
                    Destroy(node.Pawn.gameObject);
                    node.Pawn = null;
                }
            }
        }
    }

    public bool ifPlayerHero;
    public bool ifComputerHero;

    /// <summary>
    /// 4.检查战斗结果
    /// </summary>
    /// <param name="ifEnd"></param>
    /// <param name="CheckIfEndBattle("></param>
    /// <returns></returns>
    public (bool ifEnd, bool ifVictory) CheckIfEndBattle()
    {
        bool ifComputerAlive = false;
        bool ifPlayerAlive = false;
        bool ifPlayerHeroAlive = false;
        bool ifComputerHeroAlive = false;
        foreach (var node in grids)
        {
            if (node.Pawn != null)
            {
                if (!node.Pawn.campIsSelf)
                {
                    ifComputerAlive = true;
                    if (node.Pawn.ifHero)
                        ifComputerHeroAlive = true;
                }
                else
                {
                    ifPlayerAlive = true;
                    if (node.Pawn.ifHero)
                        ifPlayerHeroAlive = true;
                }
            }
        }

        if (GameManager.instance.ifHeroMode)
        {
            // 如果电脑有英雄且电脑英雄不存活
            if (ifComputerHero && !ifComputerHeroAlive)
            {
                return (true, ifPlayerAlive);
            }

            // 如果玩家有英雄且玩家英雄不存活
            if (ifPlayerHero && !ifPlayerHeroAlive)
            {
                return (true, ifPlayerHeroAlive);
            }
        }

        
        if (!GameManager.instance.ifHeroMode)
        {
            if(GetGridNode(1,1).Pawn == null || !GetGridNode(1,1).Pawn.campIsSelf)
            {
                return(true, false);
            }
        }
        // 如果玩家和电脑均还有单位存活
        if (ifComputerAlive && ifPlayerAlive)
        {
            return (false, ifPlayerAlive);
        }
        else
        {
            return (true, ifPlayerAlive);
        }
    }

    public List<GridNode> GetAvaliableNodes(GridNode basedNode, bool ifComputer)
    {
        List<GridNode> nodes = new List<GridNode>();

        foreach (var node in grids)
        {
            if (node.Pawn == null)
            {
                if (ifComputer && node.layer >= 4)
                    nodes.Add(node);
                else if (!ifComputer && node.layer <= 3)
                    nodes.Add(node);

            }
        }

        nodes.Sort((node1, node2) => { return GetDistance(node1, basedNode) - GetDistance(node2, basedNode) > 0 ? 1 : -1; });
        return nodes;
    }

    public static float GetDistance(GridNode based, GridNode next)
    {
        return Mathf.Abs(based.layer - next.layer) + Mathf.Abs(based.number - next.number);
    }

    public List<Pawn> BattlePawns = new List<Pawn>();

    public void OnBattleStart()
    {
        BattlePawns.Clear();
        ifPlayerHero = false;
        ifComputerHero = false;
        foreach (var node in grids)
        {
            if (node.Pawn != null)
            {
                BattlePawns.Add(node.Pawn);

                if (node.Pawn.ifHero)
                {
                    if (node.Pawn.campIsSelf)
                    {
                        ifPlayerHero = true;
                    }
                    else
                    {
                        ifComputerHero = true;
                    }
                }
            }
        }
    }

    /// <summary>
    /// 5.战斗结束了 通知所有单位
    /// </summary>
    public void OnBattleEnd()
    {
        foreach (var pawn in BattlePawns)
        {
            if (pawn != null)
            {
                pawn.OnBattleOver();
            }
        }
    }

    public List<Pawn> GetDistancePawn(GridNode grid)
    {
        List<Pawn> pawns = new List<Pawn>();
        if (grid == null)
        {
            Debug.Log("grid");
            return null;
        }
        foreach (var node in grids)
        {
            float i = GetDistance(grid, node);
            if (i <= 1)
            {
                if (node.Pawn != null)
                {
                    pawns.Add(node.Pawn);
                }
            }
        }
        return pawns;
    }

}
